package recharge

import (
	"context"
	"errors"
	"gitee.com/liuxuezhan/ar-platform/assets-rpc/internal/dao/dto"
	"time"

	schema "gitee.com/liuxuezhan/ar-platform/assets-rpc/internal/dao/schema/recharge"
	"gitee.com/liuxuezhan/ar-platform/assets-rpc/internal/svc"
	"gitee.com/liuxuezhan/ar-platform/assets-rpc/pkg/xerrors"
	"gitee.com/liuxuezhan/ar-platform/assets-rpc/rpc"
	"github.com/zeromicro/go-zero/core/logc"
	"gorm.io/gorm"
)

const (
	PENDING int32 = 1
	SUCCESS int32 = 2
	FAIL    int32 = 3
	TIMEOUT int32 = 4
)

type RechargeOrderModel struct {
	ctx context.Context
	db  *gorm.DB
}

func NewRechargeOrderModel(ctx context.Context, db *gorm.DB) *RechargeOrderModel {
	return &RechargeOrderModel{
		ctx: ctx,
		db:  db,
	}
}

func (model *RechargeOrderModel) getDb() *gorm.DB {
	if model.db != nil {
		return model.db
	}

	return svc.Db
}

func (model *RechargeOrderModel) CreateRechargeOrder(data *schema.RechargeOrder) error {
	// create recharge order
	table := data.TableName()
	res := model.getDb().Model(&schema.RechargeOrder{}).Table(table).Create(data)
	if err := res.Error; err != nil {
		logc.Error(model.ctx, "orderModel-CreateRechargeOrder,err", err)
		return err
	}
	return nil
}

func (model *RechargeOrderModel) GetRechargeOrderList(in *rpc.RechargeListRequest) ([]schema.RechargeOrder, int64, error) {
	var orders []schema.RechargeOrder
	var total int64

	query := model.db.Model(&schema.RechargeOrder{}).Where("user_id = ?", in.UserId)

	if in.OrderNo != "" {
		query = query.Where("order_no = ?", in.OrderNo)
	}
	if in.StartTime != "" {
		query = query.Where("created_at >= ?", in.StartTime)
	}
	if in.EndTime != "" {
		query = query.Where("created_at <= ?", in.EndTime)
	}
	if in.Status != 0 {
		query = query.Where("status = ?", in.Status)
	}
	if in.ChannelId != 0 {
		query = query.Where("channel_id = ?", in.ChannelId)
	}
	if in.Type != 0 {
		query = query.Where("type = ?", in.Type)
	}

	// Count total records
	if err := query.Count(&total).Error; err != nil {
		logc.Error(model.ctx, "orderModel-GetRechargeOrderList-count,err", err)
		return nil, 0, err
	}

	// Fetch paginated records
	offset := (in.Page - 1) * in.PageSize
	if err := query.Offset(int(offset)).Limit(int(in.PageSize)).Order("created_at desc").Find(&orders).Error; err != nil {
		logc.Error(model.ctx, "orderModel-GetRechargeOrderList-find,err", err)
		return nil, 0, err
	}

	return orders, total, nil
}

func (model *RechargeOrderModel) GetRechargeOrderListPage(in *rpc.RechargeOrderListPageRequest) (*rpc.RechargeOrderListPageResponse, error) {
	var rechargeOrderList []*schema.RechargeOrder
	offset := in.Page.PageSize * (in.Page.PageNo - 1)

	// 查询所有用户银行信息
	query := model.db.Model(schema.RechargeOrder{})
	if in.Param.OrderNo != "" {
		query = query.Where("order_no = ?", in.Param.OrderNo)
	}
	if in.Param.StartTime != "" {
		query = query.Where("created_at >= ?", in.Param.StartTime)
	}
	if in.Param.EndTime != "" {
		query = query.Where("created_at <= ?", in.Param.EndTime)
	}
	if in.Param.Status != 0 {
		query = query.Where("status = ?", in.Param.Status)
	}
	if in.Param.ChannelId != 0 {
		query = query.Where("channel_id = ?", in.Param.ChannelId)
	}
	if len(in.Param.Type) > 0 {
		query = query.Where("type in ?", in.Param.Type)
	}
	if in.Param.DepositType != 0 {
		query = query.Where("deposit_type = ?", in.Param.DepositType)
	}
	if in.Param.RefId != 0 {
		query = query.Where("ref_id = ?", in.Param.RefId)
	}
	if in.Param.GoonStatus != 0 {
		query = query.Where("goon_status = ?", in.Param.GoonStatus)
	}
	if in.Param.UserId != 0 {
		query = query.Where("user_id = ?", in.Param.UserId)
	}
	if len(in.Param.Amount) > 0 && in.Param.Amount[1] != 0 {
		query = query.Where("Amount >= ? and Amount <= ?", in.Param.Amount[0], in.Param.Amount[1])
	}

	var total int64
	query = query.Count(&total).Limit(int(in.Page.PageSize)).Offset(int(offset)).Order("created_at desc")
	query.Find(&rechargeOrderList)

	var rechargeOrderInfoList []*rpc.RechargeOrder

	if len(rechargeOrderList) == 0 {
		return &rpc.RechargeOrderListPageResponse{
			RechargeOrderList: rechargeOrderInfoList,
			Total:             total,
		}, nil
	}

	for _, rechargeOrder := range rechargeOrderList {
		rechargeOrderInfoList = append(rechargeOrderInfoList, &rpc.RechargeOrder{
			Id:              rechargeOrder.ID,
			UserId:          rechargeOrder.UserID,
			BankUpi:         rechargeOrder.BankUpi,
			OrderId:         rechargeOrder.OrderId,
			OrderNo:         rechargeOrder.OrderNo,
			Type:            rechargeOrder.Type,
			Amount:          rechargeOrder.Amount,
			ChannelId:       rechargeOrder.ChannelID,
			Status:          rechargeOrder.Status,
			CreatedAt:       rechargeOrder.CreatedAt,
			UpdatedAt:       rechargeOrder.UpdatedAt,
			ReturnJson:      rechargeOrder.ReturnJson,
			TransferReceipt: rechargeOrder.TransferReceipt,
			CustomerInfo:    rechargeOrder.CustomerInfo,
			VipLevel:        rechargeOrder.VipLevel,
			ActualAmount:    rechargeOrder.ActualAmount,
			DepositTime:     rechargeOrder.DepositTime,
			DepositType:     rechargeOrder.DepositType,
			RefId:           rechargeOrder.RefId,
			GoonStatus:      rechargeOrder.GoonStatus,
		})
	}
	return &rpc.RechargeOrderListPageResponse{
		RechargeOrderList: rechargeOrderInfoList,
		Total:             total,
	}, nil
}

// GetInitOrder 获取初始订单
func (model *RechargeOrderModel) GetInitOrder(orderNo string) (*schema.RechargeOrder, error) {
	order := &schema.RechargeOrder{}
	result := model.db.Where("order_no", orderNo).First(order)
	if err := result.Error; err != nil {
		// 订单不存在
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, xerrors.ErrRechargeOrderNotExist
		}
		return nil, err
	}
	// 订单已处理
	if order.Status != PENDING && order.Status != TIMEOUT {
		return nil, xerrors.ErrRechargeOrderProcessed
	}
	return order, nil
}

// UpdateStatusSuccess 修改订单状态【成功】
func (model *RechargeOrderModel) UpdateStatusSuccess(orderNo string, json string) error {
	result := model.db.Model(&schema.RechargeOrder{}).
		Where("order_no", orderNo).
		Where("status IN(?, ?)", PENDING, TIMEOUT).
		Updates(map[string]interface{}{
			"status":       SUCCESS,
			"return_json":  json,
			"deposit_time": time.Now().Unix(),
		})
	if err := result.Error; err != nil {
		return err
	}
	if result.RowsAffected == 0 {
		return xerrors.ErrRechargeOrderProcessed
	}
	return nil
}

// UpdateStatusFailed 修改订单状态【失败】
func (model *RechargeOrderModel) UpdateStatusFailed(orderNo string, json string) error {
	result := model.db.Model(&schema.RechargeOrder{}).
		Where("order_no", orderNo).
		Where("status IN(?,?)", PENDING, TIMEOUT).
		Updates(map[string]interface{}{
			"status":      FAIL,
			"return_json": json,
		})
	if err := result.Error; err != nil {
		return err
	}
	if result.RowsAffected == 0 {
		return xerrors.ErrRechargeOrderProcessed
	}
	return nil
}

// UpdateOrderId 修改第三方订单号
func (model *RechargeOrderModel) UpdateOrderId(orderNo string, orderId string) error {
	result := model.db.Model(&schema.RechargeOrder{}).
		Where("order_no", orderNo).
		Where("status", PENDING).
		Updates(map[string]interface{}{
			"order_id": orderId,
		})
	if err := result.Error; err != nil {
		return err
	}
	if result.RowsAffected == 0 {
		return xerrors.ErrRechargeOrderProcessed
	}
	return nil
}

// GetFirstRechargeOrder 获取首次充值订单
func (model *RechargeOrderModel) GetFirstRechargeOrder(userId int64) (*schema.RechargeOrder, error) {
	order := &schema.RechargeOrder{
		UserID: userId,
	}
	result := model.db.Model(&schema.RechargeOrder{}).
		Where("user_id", userId).
		Where("status", SUCCESS).
		First(order)
	if err := result.Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return order, nil
		}
		return nil, err
	}
	return order, nil
}

type UserData struct {
	TotalAmount float64 `gorm:"column:total_amount"`
	UserID      int64   `gorm:"column:user_id"`
}

func (model *RechargeOrderModel) SumUsersAmountInTimeDuration(in dto.SumUsersAmountInTimeDurationDto) (*dto.SumResponse, error) {
	query := model.db.Model(schema.RechargeOrder{})
	var userData dto.SumResponse
	if in.Start > 0 {
		query = query.Where("deposit_time >= ?", in.Start)
	}
	if in.End > 0 {
		query = query.Where("deposit_time <= ?", in.End)
	}
	result := query.
		Select("SUM(amount) as total_amount,user_id").
		Where("user_id in (?) ", in.UserIds).
		Group("user_id").
		Scan(&userData.Data)

	if result.Error != nil {
		return nil, result.Error
	}

	return &userData, nil
}
